//
//  LCSpeakButton.m
//  语音合成识别
//
//  Created by 九酷 on 2018/5/11.
//  Copyright © 2018年 九酷. All rights reserved.
//

#import "LCSpeakButton.h"
#import "LCSpeakConfig.h"

#pragma clang diagnostic ignored "-Wdeprecated-declarations"

@interface LCSpeakButton ()

@property (nonatomic,strong)NSMutableArray* synthesisTexts;
@property (nonatomic,strong)NSMutableArray* addTextQueue; /*used with textFromFile*/

@end

@implementation LCSpeakButton

+ (BOOL)isFileSynthesisEnabled{
    return textFromFile;
}
+ (BOOL)isSpeakEnabled{
    return isSpeak;
}
+ (void)setFileSynthesisEnabled:(BOOL)isEnabled{
    textFromFile = isEnabled;
    displayAllSentences = !textFromFile;
}
+ (void)setSpeakEnabled:(BOOL)isEnabled{
    isSpeak = isEnabled;
}
-(void)configureSDK{
    NSLog(@"TTS version info: %@", [BDSSpeechSynthesizer version]);
    [BDSSpeechSynthesizer setLogLevel:BDS_PUBLIC_LOG_VERBOSE];
    [[BDSSpeechSynthesizer sharedInstance] setSynthesizerDelegate:self];
    [self configureOnlineTTS];
    [self configureOfflineTTS];
}
- (void)dealloc {
    [self synthesizerCanceled];
    NSLog(@"__func__dealloc = %s", __func__);
}
- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setupUI];
    }
    return self;
}
-(YYAnimatedImageView *)webImageView{
    if (!_webImageView) {
        _webImageView =[[YYAnimatedImageView alloc]initWithFrame:CGRectMake(0, 0, self.size.width, self.size.height)];
        _webImageView.contentMode = UIViewContentModeScaleAspectFill;
        _webImageView.clipsToBounds = YES;
        _webImageView.backgroundColor = [UIColor whiteColor];
    }
    return _webImageView;
}
- (void)setupUI {
    [self addSubview:self.webImageView];
    _webImageView.image = [UIImage imageNamed:@"ia_off_voice"];
    self.synthesisTexts = [[NSMutableArray alloc] init];
    self.addTextQueue = [[NSMutableArray alloc] init];
    self.playNumber = 0;
    progressValue = 0;
    [self configureSDK];
    isClickState = YES;
    isOne   = YES;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self clickOnBut];
}
- (void)didChangeLCPlayerValue{
    if (_LCPlayer.kstatus == LCMusicPlayerStatusPlaying) {
        self.PlayAudio++;
        [_LCPlayer pause];//暂停播放
        _LCPlayer.comeFrome = 1;//播放的锁屏判断.
    }else if (self.PlayAudio > 0 && _LCPlayer.kstatus == LCMusicPlayerStatusPaused) {
        [_LCPlayer play];//继续播放
        _LCPlayer.comeFrome = 0;
    }
}

-(void)clickOnBut {
    if (isOne == YES) {
        if (_clickSpeak != nil) {
            _clickSpeak();
        }
        [_LCPlayer setupAVAudioBackgroundPlay];
        isOne = NO;
        isClickState = YES;
        if (_LCPlayer.kstatus == LCMusicPlayerStatusPlaying) {
            [self didChangeLCPlayerValue];
        }
        [self speakBegin];//开始解析
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if ([[BDSSpeechSynthesizer sharedInstance] synthesizerStatus] == BDS_SYNTHESIZER_STATUS_CANCELLED) {
                [self isChooseState];
                isClickState = YES;
            }
        });
    }else{
        [self isChooseState];
        [self didChangeLCPlayerValue];
    }
}
- (void)changeStateAndImage {
    NSLog(@"self.selected = %d", self.selected);
    self.selected = isClickState;
    NSLog(@"self.selected = %d", self.selected);
    if (self.selected) {
        NSURL *url = [[NSBundle mainBundle] URLForResource:@"speak_play" withExtension:@"gif"];
        [_webImageView yy_setImageWithURL:url placeholder:nil];
    }else{
        _webImageView.image = [UIImage imageNamed:@"ia_off_voice"];
    }
}
#pragma mark - 点击状态改变
-(void)isChooseState {
    if([[BDSSpeechSynthesizer sharedInstance] synthesizerStatus] == BDS_SYNTHESIZER_STATUS_PAUSED){
        [[BDSSpeechSynthesizer sharedInstance] resume];
    }else if([[BDSSpeechSynthesizer sharedInstance] synthesizerStatus] == BDS_SYNTHESIZER_STATUS_WORKING){
        [[BDSSpeechSynthesizer sharedInstance] pause];
    }else if([[BDSSpeechSynthesizer sharedInstance] synthesizerStatus] == BDS_SYNTHESIZER_STATUS_IDLE){
        [self speakBegin];
    }
}
#pragma mark - 开始 speakBegin
-(void)speakBegin {
    self.addArrayData = [NSMutableArray array];
    NSAttributedString* string = [[NSAttributedString alloc] initWithString:self.strControl];
    NSInteger number = string.length;
    NSInteger numerStr = number/512;
    for (int i = 0; i< numerStr+1; i++) {
        NSAttributedString * str = [[NSAttributedString alloc]init];
        if (i == numerStr) {
            str = [string attributedSubstringFromRange:NSMakeRange(i*512, number - i*512)];
        }else{
            str = [string attributedSubstringFromRange:NSMakeRange(i*512, 512)];
        }
        [self.addArrayData addObject:str];
    }
    [self PlayerNumber:self.playNumber :string];
}
-(void)PlayerNumber :(NSInteger)page :(NSAttributedString *)string
{
    NSInteger sentenceID;
    NSError* err = nil;
    if(isSpeak){
        sentenceID = [[BDSSpeechSynthesizer sharedInstance] speakSentence:[self.addArrayData[self.playNumber] string] withError:&err];
    }else{
        sentenceID = [[BDSSpeechSynthesizer sharedInstance] synthesizeSentence:[self.addArrayData[self.playNumber] string] withError:&err];
    }
    if(err == nil){
        NSMutableDictionary *addedString = [[NSMutableDictionary alloc] initWithObjects:@[string, [NSNumber numberWithInteger:sentenceID], [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:0]] forKeys:@[@"TEXT", @"ID", @"SPEAK_LEN", @"SYNTH_LEN"]];
        [self.synthesisTexts addObject:addedString];
        [self updateSynthProgress];
        if(self.synthesisTexts.count == 1){
        }
    }
    else{
        [self displayError:err withTitle:@"Add sentence Error"];
    }
}
-(void)configureOnlineTTS{
    [[BDSSpeechSynthesizer sharedInstance] setApiKey:API_KEY withSecretKey:SECRET_KEY];
    [[BDSSpeechSynthesizer sharedInstance] setSynthParam:@(BDS_SYNTHESIZER_SPEAKER_FEMALE) forKey:BDS_SYNTHESIZER_PARAM_SPEAKER];
    [[BDSSpeechSynthesizer sharedInstance] setSynthParam:@(2) forKey:BDS_SYNTHESIZER_PARAM_ONLINE_REQUEST_TIMEOUT];
    // 音量
    [[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:9] forKey:BDS_SYNTHESIZER_PARAM_VOLUME];
}
-(void)configureOfflineTTS{
    NSError *err = nil;
    // 在这里选择不同的离线音库（请在XCode中Add相应的资源文件），同一时间只能load一个离线音库。根据网络状况和配置，SDK可能会自动切换到离线合成。
    NSString* offlineEngineSpeechData = [[NSBundle mainBundle] pathForResource:@"Chinese_And_English_Speech_Female" ofType:@"dat"];
    NSString* offlineChineseAndEnglishTextData = [[NSBundle mainBundle] pathForResource:@"Chinese_And_English_Text" ofType:@"dat"];
    err = [[BDSSpeechSynthesizer sharedInstance] loadOfflineEngine:offlineChineseAndEnglishTextData speechDataPath:offlineEngineSpeechData licenseFilePath:nil withAppCode:APP_ID];
    if(err){
        [self displayError:err withTitle:@"Offline TTS init failed"];
        return;
    }
    //    [TTSConfigViewController loadedAudioModelWithName:@"Chinese female" forLanguage:@"chn"];
    //    [TTSConfigViewController loadedAudioModelWithName:@"English female" forLanguage:@"eng"];
}
-(void)displayError:(NSError*)error withTitle:(NSString*)title{
    //    NSString* errMessage = error.localizedDescription;
    //    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:errMessage preferredStyle:UIAlertControllerStyleAlert];
    //    if(alert){
    //        UIAlertAction* dismiss = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
    //                                                        handler:^(UIAlertAction * action) {}];
    //        [alert addAction:dismiss];
    //        [self presentViewController:alert animated:YES completion:nil];
    //    }
    //    else{
    //        UIAlertView *alertv = [[UIAlertView alloc] initWithTitle:title message:errMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    //        if(alertv){
    //            [alertv show];
    //        }
    //    }
}

-(void)updateSynthProgress{
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] init];
    if(displayAllSentences){
        for(NSDictionary* contentDict in self.synthesisTexts){
            [str appendAttributedString:[contentDict objectForKey:@"TEXT"]];
        }
    }
    else{
        if(self.synthesisTexts.count > 0){
            NSDictionary* contentDict = [self.synthesisTexts objectAtIndex:0];
            [str appendAttributedString:[contentDict objectForKey:@"TEXT"]];
        }
    }
}
-(void)addFileTextLoop
{
    if(self.addTextQueue.count > 0){
        NSAttributedString* string = [[NSAttributedString alloc] initWithString:[self.addTextQueue objectAtIndex:0]];
        [self.addTextQueue removeObjectAtIndex:0];
        NSInteger sentenceID;
        NSError* err = nil;
        if(isSpeak)
            sentenceID = [[BDSSpeechSynthesizer sharedInstance] speakSentence:[string string] withError:&err];
        else
            sentenceID = [[BDSSpeechSynthesizer sharedInstance] synthesizeSentence:[string string] withError:&err];
        if(err == nil){
            NSMutableDictionary *addedString = [[NSMutableDictionary alloc] initWithObjects:@[string, [NSNumber numberWithInteger:sentenceID], [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:0]] forKeys:@[@"TEXT", @"ID", @"SPEAK_LEN", @"SYNTH_LEN"]];
            [self.synthesisTexts addObject:addedString];
            [self updateSynthProgress];
        }
        else{
            [self displayError:err withTitle:@"Add sentence Error"];
            [self.addTextQueue removeAllObjects];
        }
    }
    if(self.addTextQueue.count > 0){
        [self performSelector:@selector(addFileTextLoop) withObject:nil afterDelay:0.2];
    }
}
- (void)textViewDidChange:(UITextView *)textView
{
    NSLog(@"11111");
}
- (NSAttributedString *)string:(NSString *)string withColor:(UIColor *)color
{
    NSMutableAttributedString *colorfulString = [[NSMutableAttributedString alloc] initWithString:string];
    [colorfulString addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, [colorfulString length])];
    [colorfulString addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue" size:14.0] range:NSMakeRange(0, [colorfulString length])];
    return colorfulString;
}

-(void)refreshAfterProgressUpdate:(NSMutableDictionary*)updatedSentence{
    NSString* totalText = [((NSAttributedString*)[updatedSentence objectForKey:@"TEXT"]) string];
    NSInteger readOffset = [[updatedSentence objectForKey:@"SPEAK_LEN"] integerValue];
    NSInteger synthOffset = [[updatedSentence objectForKey:@"SYNTH_LEN"] integerValue];
    
    NSLog(@"UPDATE PROGRESS: ReadLen: %ld, SynthLen: %ld, TotalLen: %lu", (long)readOffset, (long)synthOffset, (unsigned long)totalText.length);
    
    NSRange readRange = NSMakeRange(0, readOffset);
    NSRange synthRange = NSMakeRange(readOffset, synthOffset-readOffset);
    NSRange unprocessedRange = NSMakeRange(synthOffset, totalText.length-synthOffset);
    
    NSString* readText = [totalText substringWithRange: readRange];
    NSString* synthesizeSentenceText = [totalText substringWithRange: synthRange];
    NSString* unProcessedText = [totalText substringWithRange: unprocessedRange];
    
    NSMutableAttributedString *allMessage = [[NSMutableAttributedString alloc] initWithAttributedString:[self string: readText withColor: [UIColor redColor]]];
    [allMessage appendAttributedString:[self string: synthesizeSentenceText withColor: [UIColor blueColor]]];
    [allMessage appendAttributedString:[self string: unProcessedText withColor: [UIColor blackColor]]];
    [updatedSentence setObject:allMessage forKey:@"TEXT"];
    [self updateSynthProgress];
}

#pragma mark - implement BDSSpeechSynthesizerDelegate
#pragma mark - 开始合成
- (void)synthesizerStartWorkingSentence:(NSInteger)SynthesizeSentence{
    NSLog(@"Did start synth %ld", (long)SynthesizeSentence);
}
#pragma mark - 结束合成
- (void)synthesizerFinishWorkingSentence:(NSInteger)SynthesizeSentence{
    NSLog(@"Did finish synth, %ld", (long)SynthesizeSentence);
    //分段添加数据
    if (self.playNumber < self.addArrayData.count-1) {
        self.playNumber = self.playNumber + 1;
        NSAttributedString* string = [[NSAttributedString alloc] initWithString:self.strControl];
        [self PlayerNumber:self.playNumber :string];
    }
    if(!isSpeak){
        if(self.synthesisTexts.count > 0 &&
           SynthesizeSentence == [[[self.synthesisTexts objectAtIndex:0] objectForKey:@"ID"] integerValue]){
            [self.synthesisTexts removeObjectAtIndex:0];
            [self updateSynthProgress];
        }
        else{
            NSLog(@"Sentence ID mismatch??? received ID: %ld\nKnown sentences:", (long)SynthesizeSentence);
            for(NSDictionary* dict in self.synthesisTexts){
                NSLog(@"ID: %ld Text:\"%@\"", [[dict objectForKey:@"ID"] integerValue], [((NSAttributedString*)[dict objectForKey:@"TEXT"]) string]);
            }
        }
    }
}
#pragma mark - 朗读开始
- (void)synthesizerSpeechStartSentence:(NSInteger)SpeakSentence{
    NSLog(@"Did start speak %ld", (long)SpeakSentence);
    isClickState = YES;
    [self changeStateAndImage];
}
#pragma mark - 朗读完成
- (void)synthesizerSpeechEndSentence:(NSInteger)SpeakSentence{
    NSLog(@"Did end speak %ld", (long)SpeakSentence);
    if(self.synthesisTexts.count > 0 &&
       SpeakSentence == [[[self.synthesisTexts objectAtIndex:0] objectForKey:@"ID"] integerValue]){
        [self.synthesisTexts removeObjectAtIndex:0];
        [self updateSynthProgress];
    }
    else{
        NSLog(@"Sentence ID mismatch??? received ID: %ld\nKnown sentences:", (long)SpeakSentence);
        for(NSDictionary* dict in self.synthesisTexts){
            NSLog(@"ID: %ld Text:\"%@\"", [[dict objectForKey:@"ID"] integerValue], [((NSAttributedString*)[dict objectForKey:@"TEXT"]) string]);
        }
    }
    if(self.synthesisTexts.count == 0){
        isClickState = NO;//重置
        [self changeStateAndImage];
    }
}
#pragma mark - 返回合成语音数据
- (void)synthesizerNewDataArrived:(NSData *)newData
                       DataFormat:(BDSAudioFormat)fmt
                   characterCount:(int)newLength
                   sentenceNumber:(NSInteger)SynthesizeSentence{
    NSMutableDictionary* sentenceDict = nil;
    for(NSMutableDictionary *dict in self.synthesisTexts){
        if([[dict objectForKey:@"ID"] integerValue] == SynthesizeSentence){
            sentenceDict = dict;
            break;
        }
    }
    if(sentenceDict == nil){
        NSLog(@"Sentence ID mismatch??? received ID: %ld\nKnown sentences:", (long)SynthesizeSentence);
        for(NSDictionary* dict in self.synthesisTexts){
            NSLog(@"ID: %ld Text:\"%@\"", [[dict objectForKey:@"ID"] integerValue], [((NSAttributedString*)[dict objectForKey:@"TEXT"]) string]);
        }
        return;
    }
    [sentenceDict setObject:[NSNumber numberWithInteger:newLength] forKey:@"SYNTH_LEN"];
    [self refreshAfterProgressUpdate:sentenceDict];
}
#pragma mark - 播放进度变更
- (void)synthesizerTextSpeakLengthChanged:(int)newLength
                           sentenceNumber:(NSInteger)SpeakSentence{
    //    NSLog(@"SpeakLen %ld, %d", (long)SpeakSentence, newLength);
    NSString * strTitle = [NSString stringWithFormat:@"%@",self.strControl];
    NSInteger strTitleLength = strTitle.length;//数据的总长度
    float a = newLength%strTitleLength;
    float b = a/strTitleLength;//当前进度    此次添加的数据数据的进度
    float value = b * 100;//当前进度乘以100 百分比展示    此次添加的数据数据的进度
    if (newLength == 1) {
        phaseValues = progressValue;//每当进去一个新的阶段的时候  记录一下上个阶段的进度是多少
    }
    progressValue = value+phaseValues;//总进度
    //    NSLog(@"%.4f>>>>>>>>>>>>..",progressValue);
    //    labelProgress.text = [NSString stringWithFormat:@"%.4f%%",progressValue];
    NSMutableDictionary* sentenceDict = nil;
    for(NSMutableDictionary *dict in self.synthesisTexts){
        if([[dict objectForKey:@"ID"] integerValue] == SpeakSentence){
            sentenceDict = dict;
            break;
        }
    }
    if(sentenceDict == nil){
        NSLog(@"Sentence ID mismatch??? received ID: %ld\nKnown sentences:", (long)SpeakSentence);
        for(NSDictionary* dict in self.synthesisTexts){
            NSLog(@"ID: %ld Text:\"%@\"", [[dict objectForKey:@"ID"] integerValue], [((NSAttributedString*)[dict objectForKey:@"TEXT"]) string]);
        }
        return;
    }
    
    [sentenceDict setObject:[NSNumber numberWithInteger:newLength] forKey:@"SPEAK_LEN"];
    [self refreshAfterProgressUpdate:sentenceDict];
}
- (void)synthesizerdidPause{
    isClickState = NO;
    [self changeStateAndImage];
}
- (void)synthesizerResumed{
    isClickState = YES;
    [self changeStateAndImage];
}
- (void)synthesizerCanceled{
    if([[BDSSpeechSynthesizer sharedInstance] synthesizerStatus] == BDS_SYNTHESIZER_STATUS_WORKING){
        [[BDSSpeechSynthesizer sharedInstance] cancel];
    }
    if (self.PlayAudio > 0 && _LCPlayer.kstatus == LCMusicPlayerStatusPaused) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [_LCPlayer play];//继续播放
            _LCPlayer.comeFrome = 0;
            
        });
    }
    NSLog(@"Did cancel");
}
#pragma mark - 合成器发生错误
- (void)synthesizerErrorOccurred:(NSError *)error
                        speaking:(NSInteger)SpeakSentence
                    synthesizing:(NSInteger)SynthesizeSentence{
    NSLog(@"Did error %ld, %ld", (long)SpeakSentence, SynthesizeSentence);
    if(self.addTextQueue){
        [self.addTextQueue removeAllObjects];
    }
    [self.synthesisTexts removeAllObjects];
    [self updateSynthProgress];
    [[BDSSpeechSynthesizer sharedInstance] cancel];
    [self displayError:error withTitle:@"Synthesis failed"];
}
@end
